package com.cazor.dg.app;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.cazor.common.utils.DictUtils;
import com.cazor.common.utils.StringUtils;
import com.cazor.dg.common.DgConstants;
import com.cazor.dg.common.DgSysCacheService;
import com.cazor.dg.domain.*;
import com.cazor.dg.service.*;
import com.cazor.mg.domain.MgParamLog;
import com.cazor.mg.service.IMgParamLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class AppService {
    @Resource
    private AppReqService appReqService;
    @Resource
    private IDgMonitorStationService monitorStationService;
    @Resource
    private IDgDevDeviceInstanceService devDeviceInstanceService;
    @Resource
    private IDgDeviceSensorService deviceSensorService;
    @Resource
    private IAdgLoginTokenHisService loginTokenHisService;
    @Resource
    private DgSysCacheService dgSysCacheService;
    @Resource
    private IMgParamLogService mgParamLogService;
    @Resource
    private IDgConfigContentTypeService configContentTypeService;
    @Resource
    private IDgParamDataSensorService paramDataSensorService;


    // ------------------------------------------------- 下面代码处理监测站 -----------------------------------------------
    /**
     * 批量 调用接口 新增
     * @param enforce ture 强制执行; false 仅对未提交成功的数据执行
     */
    public void monitorStationAddBatch(boolean enforce){
        LambdaQueryChainWrapper<DgMonitorStation> query = monitorStationService.lambdaQuery()
                .eq(DgMonitorStation::getValid, "1");
        // 如果不是强制执行 则仅查询未执行的数据
        if (!enforce) {
            query.eq(DgMonitorStation::getStatus, 0);
        }
        List<DgMonitorStation> list = query.list();
        int count = CollectionUtil.size(list);
        if( count > 0 ) {
            for (DgMonitorStation dgMonitorStation : list) {
                monitorStationAdd(dgMonitorStation);
            }
        }
    }

    /**
     * 调用接口新增 监测站
     * @param id 数据id
     * @param enforce ture 强制执行; false 仅对未提交成功的数据执行
     */
    public void monitorStationAddById(Long id, boolean enforce) {
        DgMonitorStation dgMonitorStation = monitorStationService.getById(id);
        if (dgMonitorStation.getStatus() == 0 || enforce) {
            monitorStationAdd(dgMonitorStation);
        }
    }

    /**
     * 监测站数据 提交接口
     * @param dgMonitorStation
     */
    public void monitorStationAdd(DgMonitorStation dgMonitorStation) {
        JSONObject rtn = appReqService.monitorStationAdd(dgMonitorStation);
        log.info("monitorStationAdd-接口返回:{}", rtn.toString());
        // 如果提交成功 则更新 Status
        if (rtn.getInteger("code") == 200 && rtn.getBoolean("success")) {
            JSONObject result = rtn.getJSONObject("result");
            DgMonitorStation updateHis = new DgMonitorStation();
            updateHis.setId(dgMonitorStation.getId());
            updateHis.setStatus(1);
            updateHis.setStationId(result.getString("id"));
            updateHis.setUpdateTime(DateTime.now());
            monitorStationService.updateById(updateHis);
        }
    }

    // ------------------------------------------------- 下面代码处理 监测内容(采集仪) -----------------------------------------------
    /**
     *
     * 批量 调用接口 新增 监测内容(采集仪) 数据
     * @param enforce ture 强制执行; false 仅对未提交成功的数据执行
     */
    public void devDeviceInstanceAddBatch(boolean enforce) {
        LambdaQueryChainWrapper<DgDevDeviceInstance> query = devDeviceInstanceService.lambdaQuery()
                .eq(DgDevDeviceInstance::getValid, "1");
        // 如果不是强制执行 则仅查询未执行的数据
        if (!enforce) {
            query.eq(DgDevDeviceInstance::getStatus, 0);
        }
        List<DgDevDeviceInstance> list = query.list();
        int count = CollectionUtil.size(list);
        if( count > 0 ) {
            for (DgDevDeviceInstance dgDevDeviceInstance : list) {
                devDeviceInstanceAdd(dgDevDeviceInstance);
            }
        }
    }

    /**
     * 调用接口新增 监测内容 数据
     * @param id 监测内容 数据id
     * @param enforce ture 强制执行; false 仅对未提交成功的数据执行
     */
    public void devDeviceInstanceAddById(Long id, boolean enforce) {
        DgDevDeviceInstance dgDevDeviceInstance = devDeviceInstanceService.getById(id);
        if (dgDevDeviceInstance.getStatus() == 0 || enforce) {
            devDeviceInstanceAdd(dgDevDeviceInstance);
        }
    }

    public void devDeviceInstanceAdd(DgDevDeviceInstance devDeviceInstance) {
        devDeviceInstance.setContentName(null);
        devDeviceInstance.setContentType(null);
        devDeviceInstance.setDeviceModel(null);
        JSONObject rtn = appReqService.devDeviceInstanceAdd(devDeviceInstance);
        log.info("devDeviceInstanceAdd-接口返回:{}", rtn.toString());
        // 如果提交成功 则更新 Status
        if (rtn.getInteger("code") == 200 && rtn.getBoolean("success")) {
//            JSONObject result = rtn.getJSONObject("result");
            DgDevDeviceInstance updateObj = new DgDevDeviceInstance();
            updateObj.setId(devDeviceInstance.getId());
            updateObj.setStatus(1);
//            updateObj.setContentId(result.getString("id"));
            updateObj.setUpdateTime(DateTime.now());
            devDeviceInstanceService.updateById(updateObj);
        }
    }

    // ------------------------------------------------- 下面代码处理 传感器 -----------------------------------------------

    /**
     *
     * 批量 调用接口 新增 监测内容(采集仪) 数据
     * @param enforce ture 强制执行; false 仅对未提交成功的数据执行
     */
    public void deviceSensorAddBatch(boolean enforce) {
        LambdaQueryChainWrapper<DgDeviceSensor> query = deviceSensorService.lambdaQuery()
                .eq(DgDeviceSensor::getValid, "1");
        // 如果不是强制执行 则仅查询未执行的数据
        if (!enforce) {
            query.eq(DgDeviceSensor::getStatus, 0);
        }
        List<DgDeviceSensor> list = query.list();
        int count = CollectionUtil.size(list);
        if( count > 0 ) {
            for (DgDeviceSensor sensor : list) {
                deviceSensorAdd(sensor);
            }
        }
    }

    /**
     * 调用接口新增 监测内容 数据
     * @param id 监测内容 数据id
     * @param enforce ture 强制执行; false 仅对未提交成功的数据执行
     */
    public void deviceSensorAddById(Long id, boolean enforce) {
        DgDeviceSensor sensor = deviceSensorService.getById(id);
        if (sensor.getStatus() == 0 || enforce) {
            deviceSensorAdd(sensor);
        }
    }

    public void deviceSensorAdd(DgDeviceSensor sensor) {
        sensor.setContentType(DictUtils.getDictValue(DgConstants.Dict.CONTENT_TYPE, sensor.getContentType()));
        JSONObject rtn = appReqService.deviceSensorAdd(sensor);
        log.info("deviceSensorAdd-接口返回:{}", rtn.toString());
        // 如果提交成功 则更新 Status
        if (rtn.getInteger("code") == 200 && rtn.getBoolean("success")) {
//            JSONObject result = rtn.getJSONObject("result");
            DgDeviceSensor updateObj = new DgDeviceSensor();
            updateObj.setId(sensor.getId());
            updateObj.setStatus(1);
//            updateObj.setContentId(result.getString("id"));
            updateObj.setUpdateTime(DateTime.now());
            deviceSensorService.updateById(updateObj);
        }
    }

    //------------------------------------------------------------------------------------------------

    public void insertDevDeviceParamDataBatch(){
        // 获取所有有效的传感器基础数据列表
        List<DgParamDataSensor> paramDataSensorList = paramDataSensorService.getDgParamDataSensorList(null);
        int count = CollectionUtil.size(paramDataSensorList);
        if(count > 0) {
            for (DgParamDataSensor paramDataSensor : paramDataSensorList) {
                this.insertDevDeviceParamData(paramDataSensor);
            }
        }
    }

    public void insertDevDeviceParamDataBySensorId(String sensorId) {
        // 根据 传感器id 获取单个传感器数据
        DgParamDataSensor queryParams = new DgParamDataSensor();
        queryParams.setSensorId(sensorId);
        List<DgParamDataSensor> paramDataSensorList = paramDataSensorService.getDgParamDataSensorList(queryParams);
        if (CollectionUtil.size(paramDataSensorList) > 0){
            DgParamDataSensor paramDataSensor = paramDataSensorList.get(0);
//            log.info("paramDataSensor--{}", paramDataSensor.getSensorId());
            this.insertDevDeviceParamData(paramDataSensor);
        }
    }

    /**
     * 某个传感器 获取只读库中的数据 通过接口提交
     * @param paramDataSensor 传感器
     */
    public void insertDevDeviceParamData(DgParamDataSensor paramDataSensor) {
        String sensorId = paramDataSensor.getSensorId();
        Date maxReadDate = paramDataSensor.getUpdateTime();
        if (StringUtils.isBlank(sensorId) || maxReadDate == null) {
            log.warn("sensorId({}) / maxReadDate({}) 为空 不能查询"
                    , sensorId
                    , maxReadDate==null?"null":DateTime.of(maxReadDate).toString(DatePattern.NORM_DATETIME_PATTERN));
            return;
        }
        DgDeviceSensor sensor = dgSysCacheService.getDeviceSensor(paramDataSensor.getSensorId());
        DgConfigContentType configContentType = dgSysCacheService.getConfigContentType(sensor.getContentType());
        if (sensor == null || configContentType == null) {
            log.warn("传感器({})-获取到 DgDeviceSensor / DgConfigContentType 为 null", sensorId);
            return;
        }
        List<MgParamLog> paramLogList = this.getMgParamLog(sensorId, maxReadDate);
        int count = CollectionUtil.size(paramLogList);
//        log.info("paramLogList.count:{}", count);
        if (count > 0) {
            // 排序
            paramLogList = paramLogList.stream()
                    .sorted(Comparator.comparing(MgParamLog::getReadDate)).collect(Collectors.toList());
            // 对于同一个传感器 多条监测数据 每6条数据分一组
            List<List<MgParamLog>> paramLogSplitList = ListUtil.split(paramLogList, 6);
//            log.info("paramLogSplitList.count:{}", CollectionUtil.size(paramLogSplitList));
            JSONObject requestParams = null, reqJson = null;
            DgRequestHis requestHis = null;
            List<Long> requestHisIdList = new ArrayList<>(CollectionUtil.size(paramLogSplitList));
            for (List<MgParamLog> logList : paramLogSplitList) {
//                log.info("开始执行数据封装: logList.size--{}", CollectionUtil.size(logList));
                requestParams = this.initDeviceInstancesData(logList, paramDataSensor, sensor, configContentType);
//                System.out.println(requestParams);
                reqJson = appReqService.insertDevDeviceParamData(requestParams);
                if (reqJson!=null && reqJson.getInteger("code") == 200) {
                    requestHis = reqJson.getObject("requestHis", DgRequestHis.class);
                    if (requestHis!=null) {
                        requestHisIdList.add(requestHis.getId());
                    }
                } else {
                    log.error("传感器({})--提交接口异常:{}"
                            , sensorId, reqJson!=null?reqJson.getString("message"):"null");
                }
            }
            MgParamLog lastParamLog = paramLogList.get(count-1);
            DgParamDataSensor updateObj = new DgParamDataSensor();
            updateObj.setId(paramDataSensor.getId());
            updateObj.setMaxId(lastParamLog.getId());
            updateObj.setUpdateTime(lastParamLog.getReadDate());
            paramDataSensorService.updateById(updateObj);
            log.info("传感器({})--提交数据完成:hisIdList:{}", sensorId, requestHisIdList);
        } else {
            log.warn("传感器({})--获取监测数据为空！", sensorId);
        }
    }

    /**
     * 将 某个传感器的数据 封装成调用接口的json对象
     * @param paramLogList 监测数据列表
     * @param paramDataSensor 传感器
     * @param sensor 传感器数据对象
     * @param configContentType 传感器类型的参数配置
     * @return
     */
    public JSONObject initDeviceInstancesData(List<MgParamLog> paramLogList, DgParamDataSensor paramDataSensor,
                                        DgDeviceSensor sensor, DgConfigContentType configContentType) {
        int count = CollectionUtil.size(paramLogList);
        if (count > 0) {
            JSONObject deviceInstancesData = new JSONObject();
            deviceInstancesData.put("stationId", paramDataSensor.getStationId());
            deviceInstancesData.put("deviceId", paramDataSensor.getDeviceId());
            deviceInstancesData.put("sensorId", paramDataSensor.getSensorId());

            JSONArray deviceParamData = new JSONArray();
            JSONObject data = null;
            for (MgParamLog mgParamLog : paramLogList) {
                data = initDevDeviceParamData(mgParamLog, sensor, configContentType);
                if (data != null) {
                    deviceParamData.add(data);
                }
            }
            if (deviceParamData.size() <= 0) {
                return null;
            }
            JSONObject rtn = new JSONObject();
            rtn.put("deviceInstancesData", deviceInstancesData);
            rtn.put("deviceParamData", deviceParamData);
            return rtn;
        }
        return null;
    }

    /**
     * 单个 监测数据封装成提交的报文格式
     * @param mgParamLog 只读库 单条 监测数据
     * @param sensor 传感器对象
     * @param configContentType 传感器对应的类型的数据配置
     * @return 接口报文json对象
     */
    private JSONObject initDevDeviceParamData(MgParamLog mgParamLog, DgDeviceSensor sensor, DgConfigContentType configContentType) {
        String jsonInfo = mgParamLog.getJsonInfo();
        if (StringUtils.isBlank(jsonInfo)) {
            log.warn("jsonInfo 为空");
            return null;
        }
        JSONObject info = JSON.parseObject(jsonInfo);
        String keys = configContentType.getParamKeys();
        String unit = configContentType.getParamUnit();
        List<String> keyList = StrUtil.split(keys, ",");

        String val = "";
        for (String key : keyList) {
            val += info.getString(key)+",";
        }
        if (StringUtils.isBlank(val)) {
            return null;
        } else {
            val = StrUtil.removeSuffix(val, ",");
        }
        JSONObject data = new JSONObject();
        data.put("originValue", val);
        data.put("value", val);
        data.put("type", "1");
        data.put("unit", unit);
        data.put("dataTime", DateTime.of(mgParamLog.getReadDate()).toString(DatePattern.NORM_DATETIME_PATTERN));
        return data;
    }

    /**
     * 获取 某个传感器(sensorId) 大于某时间(maxReadDate) 的所有记录数据
     * @param sensorId 传感器id
     * @param maxReadDate 上次最大的检测时间
     * @return 列表
     */
    public List<MgParamLog> getMgParamLog(String sensorId, Date maxReadDate) {
        log.info("sensorId={}, maxReadDate={}, maxReadDateStr={}"
                ,  sensorId, maxReadDate, DateTime.of(maxReadDate).toString(DatePattern.NORM_DATETIME_PATTERN));
        MgParamLog queryParams = new MgParamLog();
        queryParams.setParentCode(sensorId);
        Map<String, Object> params = new HashMap<>();
        params.put("beginReadDate", maxReadDate);
        queryParams.setParams(params);

        return mgParamLogService.selectMgParamLogList(queryParams);
    }


}
